cc-pocket · ui 2.1 · defaults + voice + results · master

Defaults + Voice + Results Master v1

S3 + V3 + R3, built. Every frame below is the same live component under different props, so the geometry in the handoff tables is measured from what you are looking at rather than described beside it. Visible copy is the existing resource text in both locales; every catalogue value is the inspected fixture. Three Compose surfaces change; nothing else does.

3 surfaces
Settings · Composer · Sessions
402 · 390 · 320 · 280
+ 200% · EN/ZH · dark/light
no protocol change
no daemon · relay · desktop
1

Agent & session defaults · S3

One unlabeled summary container is added. Order, controls and callbacks are untouched.

The page keeps its exact sequence: default agent, new-session permission mode, default model scoped to the selected agent, default effort scoped to the selected agent, conditional Fast, context window presets and custom, per-model windows, agent filter. Every existing callback fires from the same row it fires from today.

The addition is one read-only low container directly under the title. It prints existing group labels against currently stored values and owns no string of its own — no heading, no framing sentence, no derived text. It is not focusable and consumes no target budget.

Fast appears in the summary only while a priority model is selected, matching the row's own visibility rule. Omitting it under priority would let the summary imply a complete launch configuration while hiding one of its defaults.

01 · top · dark · EN · 402
Summary, then agent, then mode, then model — the existing order, with the answer to “what runs next” resolved above the fold. Codex is the stored agent, so model and effort below carry for Codex.
02 · model + effort + Fast · scrolled
The inspected catalogue in full: gpt-5.6-sol selected, then gpt-5.5 and the specialized long-context id. Efforts run Default, low, medium, high, xhigh, max, ultra with ultra stored. Fast follows because this model advertises priority.
03 · later groups · scrolled
Context window presets with its custom escape, per-model windows keyed by the real ids, then the agent filter — all unchanged in structure, order and behaviour. Preset and window values remain daemon-owned and are not enumerated here.
04 · 中文 · light · 390
Exact ZH resource copy: title Agent 与会话默认项, labels 默认智能体 · 新会话默认模式 · 默认模型 · 默认推理强度 · 快速模式. Model ids and effort values stay literal in both locales because they are data, not copy.
05 · long id · 320
The specialized id is selected and wraps on characters in the row. No ellipsis, no shrink, no sideways scroll.
06 · long id in summary · 280
At the narrowest supported width the summary's label column and its value stack rather than compress, and the id wraps to three lines fully readable.
07 · 200% · EN
At double type the title wraps and the lists grow; the summary keeps the five stored values on the first screen instead of stopping inside the agent list. Radio targets rise to 58 dp.
08 · 200% · 中文 · light
The hardest settings combination on the board. Label and value wrap independently inside the summary; nothing clips against the container's 14 dp padding.
2

Voice-aware composer · V3

All eight states. Ribbon above the field, one wrapping accessory lane below it.

The two-layer composer is unchanged: full-width multiline field above an accessory row. What moves is the written state — the existing queue, upload and transcription-failure strings now sit in one ribbon slot above the field, so the reason a control behaves unusually arrives before the control.

One restrained mark separates informational from failure by shape — a small dot against a square — so the distinction survives greyscale. The ribbon is a live region; it announces on change and never on every recomposition.

Transcript, context disclosure, Quick Actions, Model Picker, recording behaviour and the desktop composer are all untouched. No predicate changes: the same conditions that produce each control today produce it here.

09 · idle · empty
No ribbon, no actions. Mic is the accessory action and lives in the field's trailing slot; attach, model, switcher and context sit in the lane.
10 · staged draft
Field keeps Mic; Send is independently reachable in the lane. Still no ribbon — nothing unusual is happening.
11 · streaming · empty
Stop only. No Mic and no Send exist in this state. The ribbon carries Working… — sends will queue.
12 · streaming · staged
Mic returns to the field; Stop and Send are independently reachable. Send queues into the running turn, which is what the ribbon already said.
13 · upload in flight
Mic stays in the field. The action slot holds progress with role=status — there is no Send composable and nothing announces a disabled Send.
14 · recording + streaming
RecordingBar replaces the ordinary composer entirely. Cancel, waveform, timer, Done — nothing added. The separate Stop row below is the only agent-turn action that survives.
15 · transcribing + streaming
Same bar, spinner in place of the waveform, Transcribing… written beside it. Stop remains reachable throughout both capture phases.
16 · voice failure + draft
Square mark, failure chip, and the field's trailing action becomes Retry voice input in place of Mic. Send stays separately reachable for the staged draft; no third retry button is added.
Wrapping proof · full accessory set incl. switcher · streaming + staged
17 · 390 · 中文
Exact ZH: 正在运行 — 发送将排队. Actions take their own row from 390 down once the switcher is present.
18 · 320 · light
Stop and Send wrap as whole controls onto a full-width second line, each keeping 48 dp of height and an equal share of the width.
19 · 280 · stress
The lane's leading group wraps internally too: context drops beneath attach, model and switcher rather than overflowing them.
20 · 200% · 中文 · upload
At double type every accessory keeps 58 dp and the lane fully destacks. The ZH upload string wraps across two lines in the ribbon without clipping the field below.
3

New Result in Sessions · R3

One mark changes. Precedence, derivation, persistence and ordering do not.
21 · two New Results · dark · 402
Two independent New Result rows sit in Active above one Running; Complete is in Recent. Each row clears on its own authoritative open — they are not a single grouped notice.
22 · precedence ladder · light
All six rungs adjacent, in fixed order: filled diamond, hollow diamond, square, filled dot, half dot, hollow dot. Ordering shown is the daemon's; this proves only that the marks stay separable when neighbours.
23 · 中文 · 200%
有新结果 stays load-bearing at double type; the mark scales to 14 dp and the row grows rather than truncating. The written label, not the mark, is what a screen reader reports.
24 · 320 · light · ladder
At the narrow width state word and metadata wrap onto separate lines within the same row; the mark column never moves.
Half-filled mark · exact geometry
size 10.dp (14.dp at fontScale ≥ 1.5)
stroke 2.dp, colour = state tone
fill leading 50% of the circle, same tone
divide vertical, through the centre
shape CircleShape, drawn not layered
Compose: one Canvas(Modifier.size(markSize))drawArc(tone, startAngle = 90f, sweepAngle = 180f, useCenter = true) for the fill, then drawCircle(tone, style = Stroke(2.dp.toPx())) for the ring. Do not build it from two overlapping Boxes; the seam shows at odd densities.
Mark vocabulary · fill is the ladder
State
Mark
Rule
Approval
filled diamond
Unchanged. Highest precedence; diamonds stay reserved for the two states that block the user.
Answer
hollow diamond
Unchanged.
Failure
square
Unchanged. The only square in the vocabulary.
Running
solid dot
Unchanged.
New Result
half-filled dot
The one change. Was a ring, which collided with Complete under greyscale. Attention tone and the written label are unchanged.
Complete
hollow ring
Unchanged.
4

Handoff

Geometry · measured from these frames
gutter 20.dp both edges, all three surfaces
summary container RoundedCornerShape(14.dp), pad 13/14.dp
summary row gap 8.dp · label column min 118.dp
group label 10.5sp · .13em tracking · uppercase
group top gap 24.dp between groups · 22.dp under summary
list divider 1.dp hairline, bottom of every row
radio / switch row min 48.dp · pad 10.dp vertical · mark 10.dp
field min 46.dp · radius 12.dp · border 1.dp
ribbon pad-bottom 9.dp · mark 8.dp · gap 8.dp
lane FlowRow · gap 8.dp · pad-top 9.dp
action min-width 84.dp · height 48.dp · radius 12.dp
session mark col fixed · gap 11.dp · row pad 12.dp vertical
target floor 48.dp normal · 58.dp at fontScale ≥ 1.5
                     field keeps its existing 46.dp minimum
Wrapping rule · one predicate
leadNeed = 196.dp + if (switcherVisible) 82.dp else 0.dp
actNeed = actionCount * 92.dp
inline = fontScale < 1.5 && (width - 40.dp) >= leadNeed + actNeed

inline → lead weight(1f), actions Arrangement.End
stacked → lead fillMaxWidth(), actions fillMaxWidth()
            each action weight(1f), height 48.dp

Both groups are FlowRows, so the leading group re-wraps internally at 280 dp before the outer rule fires. Controls never shrink below their minimum; the lane grows in height instead.

State → UI matrix
State
Ribbon
Field trailing
Actions
idle
Mic
staged
Mic
Send
streaming · empty
Working… — sends will queue
none
Stop
streaming · staged
Working… — sends will queue
Mic
Stop · Send
upload
uploading 1 of 1 — send waits
Mic
progress · status only, no Send
recording
bar replaces composer
Stop only if streaming
transcribing
Transcribing… (in bar)
bar replaces composer
Stop only if streaming
voice failure
Couldn't transcribe — try again
Retry voice input
Send if draft
Accessibility
summary container
Not focusable, not a heading. Each pair reads as “label, value”; the model id is spoken character-grouped, not as a word.
radio / switch rows
Role Radio or Switch with selected/checked state; group labels are the list heading, unchanged.
ribbon
liveRegion = Polite, announcing on text change only. The mark is decorative and excluded from semantics; the sentence carries the state.
upload slot
Role status, labelled with the existing upload string. It is never a Button and never announces disabled.
RecordingBar
Cancel recording, Done and the timer are named; the waveform is decorative. Transcribing announces once via the same live region.
session rows
“title, state, metadata”. The written state is what is spoken; the mark is decorative, so New Result and Complete are already distinct without it.
Implementation checklist
01Settings.ktInsert the summary container between title and the first group. Read the same state the groups read; render Fast only under a priority model. Add no string resource.
02Settings.ktAppend the existing agent-scope string to the model and effort group labels. Order, callbacks and capability gates unchanged.
03VoiceComposer.ktHoist the queue and upload notes into one ribbon slot above the field and route the failure chip through it. Same strings, same predicates.
04VoiceComposer.ktCollapse the accessory bands into one FlowRow pair and apply the wrapping predicate. Delete the disabled-Send branch in the upload state; emit the status slot instead.
05App.ktConfirm capture hides the ordinary composer wholesale and that the separate Stop row is the only survivor while streaming.
06SessionStateUi.ktReplace the New Result ring with the half-filled Canvas mark. Tone, label, precedence and derivation untouched.
07StateChrome.ktAdd the half-fill to the shared mark vocabulary so every consumer draws it identically.
08UiRefinementShotsAdd renders for the four widths, both locales, both themes and 200%; extend SettingsIaTest, ChatMasterV2UiTest, MobileUi20ChromeTest and SessionStateUiTest rather than adding new suites.
Acceptance matrix
Criterion
Proof
402/390/320/280 usable, nothing clipped or overlapping
01–08 · 17–19
200% text usable on all three surfaces
07 · 08 · 20 · 23
Every interactive control ≥ 48 dp; the field keeps its existing 46 dp, above the 44 dp floor
all frames
Eight composer states reachable and distinct
09–16
Multiple New Results independently discoverable
21
Precedence unchanged
22 · 24
Long and custom ids fully readable and selectable
05 · 06
Mobile Compose + UI tests only; no backend change
checklist 01–08
Forbidden by this master
protocol · daemon · relay · desktop app
routes · persistence · notification behaviour
data, server facts or visible copy
Settings landing IA · transcript · context disclosure
Quick Actions · Model Picker · recording behaviour
New Result derivation, ordering or open-to-clear
#232 · #233 · #216 · #228